package com.sky.skyopsserver.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.skyopsserver.domain.ComputerRoom;
import com.sky.skyopsserver.mapper.ComputerRoomMapper;
import com.sky.skyopsserver.service.ComputerRoomService;
import com.sky.skyopsserver.vos.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 机房信息服务实现类
 *
 * @author Administrator
 * @description 针对表【computer_room(机房信息表)】的数据库操作Service实现
 * @createDate 2025-09-13 17:43:04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ComputerRoomServiceImpl extends ServiceImpl<ComputerRoomMapper, ComputerRoom>
        implements ComputerRoomService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addComputerRoom(ComputerRoomAddReqVO reqVO) {
        log.info("开始添加机房，机房名称: {}", reqVO.getName());

        // 检查机房名称是否已存在
        if (checkComputerRoomNameExists(reqVO.getName(), null)) {
            log.error("机房名称已存在");
            throw new RuntimeException("COMPUTER_ROOM_NAME_EXISTS");
        }

        // 构建机房实体
        ComputerRoom computerRoom = ComputerRoom.builder()
                .name(reqVO.getName())
                .city(reqVO.getCity())
                .operator(reqVO.getOperator())
                .remark(reqVO.getRemark())
                .createTime(LocalDateTime.now())
                .build();

        // 保存到数据库
        boolean saved = save(computerRoom);
        if (!saved) {
            log.error("添加机房失败");
            throw new RuntimeException("COMPUTER_ROOM_ADD_FAILED");
        }

        log.info("机房添加成功，机房ID: {}", computerRoom.getId());
        return computerRoom.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateComputerRoom(ComputerRoomUpdateReqVO reqVO) {
        log.info("开始更新机房，机房ID: {}", reqVO.getId());

        // 检查机房是否存在
        ComputerRoom existingRoom = getById(reqVO.getId());
        if (Objects.isNull(existingRoom)) {
            log.error("机房不存在");
            throw new RuntimeException("COMPUTER_ROOM_NOT_EXISTS");
        }

        // 检查机房名称是否已被其他机房使用
        if (checkComputerRoomNameExists(reqVO.getName(), reqVO.getId())) {

            throw new RuntimeException("COMPUTER_ROOM_NAME_EXISTS");
        }

        // 更新机房信息
        ComputerRoom computerRoom = new ComputerRoom();
        BeanUtils.copyProperties(reqVO, computerRoom);

        boolean updated = updateById(computerRoom);
        if (!updated) {
            log.error("更新机房失败");
            throw new RuntimeException("COMPUTER_ROOM_UPDATE_FAILED");
        }

        log.info("机房更新成功，机房ID: {}", reqVO.getId());
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteComputerRoom(Long id) {
        log.info("开始删除机房，机房ID: {}", id);

        // 检查机房是否存在
        ComputerRoom existingRoom = getById(id);
        if (Objects.isNull(existingRoom)) {
            throw new RuntimeException("COMPUTER_ROOM_NOT_EXISTS");
        }

        // TODO: 检查机房下是否有主机，如果有则不允许删除
        // 这里可以添加业务逻辑检查

        boolean deleted = removeById(id);
        if (!deleted) {
            throw new RuntimeException("COMPUTER_ROOM_DELETE_FAILED");
        }

        log.info("机房删除成功，机房ID: {}", id);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchDeleteComputerRoom(List<Long> ids) {
        log.info("开始批量删除机房，机房ID列表: {}", ids);

        if (CollectionUtils.isEmpty(ids)) {
            log.error("机房ID列表不能为空");
            throw new RuntimeException("PARAM_NOT_VALID");
        }

        // 检查所有机房是否存在
        List<ComputerRoom> existingRooms = listByIds(ids);
        if (existingRooms.size() != ids.size()) {
            log.error("部分机房不存在");
            throw new RuntimeException("COMPUTER_ROOM_NOT_EXISTS");
        }

        // TODO: 检查机房下是否有主机，如果有则不允许删除

        boolean deleted = removeByIds(ids);
        if (!deleted) {
            log.error("批量删除机房失败");
            throw new RuntimeException("COMPUTER_ROOM_DELETE_FAILED");
        }

        log.info("机房批量删除成功，删除数量: {}", ids.size());
        return true;
    }

    @Override
    public ComputerRoomRspVO getComputerRoomById(Long id) {
        log.info("查询机房详情，机房ID: {}", id);

        ComputerRoom computerRoom = getById(id);
        if (Objects.isNull(computerRoom)) {

            throw new RuntimeException("COMPUTER_ROOM_NOT_EXISTS");
        }

        ComputerRoomRspVO rspVO = new ComputerRoomRspVO();
        BeanUtils.copyProperties(computerRoom, rspVO);

        return rspVO;
    }

    @Override
    public IPage<ComputerRoomRspVO> getComputerRoomPage(ComputerRoomPageReqVO reqVO) {
        log.info("分页查询机房列表，查询条件: {}", reqVO);

        // 构建分页对象
        Page<ComputerRoom> page = new Page<>(reqVO.getCurrent(), reqVO.getSize());

        // 构建查询条件
        LambdaQueryWrapper<ComputerRoom> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.hasText(reqVO.getName()), ComputerRoom::getName, reqVO.getName())
                .like(StringUtils.hasText(reqVO.getCity()), ComputerRoom::getCity, reqVO.getCity())
                .like(StringUtils.hasText(reqVO.getOperator()), ComputerRoom::getOperator, reqVO.getOperator())
                .orderByDesc(ComputerRoom::getCreateTime);

        // 执行分页查询
        IPage<ComputerRoom> computerRoomPage = page(page, queryWrapper);

        // 转换为响应VO
        IPage<ComputerRoomRspVO> rspPage = computerRoomPage.convert(computerRoom -> {
            ComputerRoomRspVO rspVO = new ComputerRoomRspVO();
            BeanUtils.copyProperties(computerRoom, rspVO);
            return rspVO;
        });

        log.info("分页查询机房列表完成，总记录数: {}", rspPage.getTotal());
        return rspPage;
    }

    @Override
    public List<ComputerRoomOptionRspVO> getAllComputerRoomOptions() {
        log.info("查询所有机房选项");

        List<ComputerRoom> computerRooms = list(new LambdaQueryWrapper<ComputerRoom>()
                .orderByAsc(ComputerRoom::getName));

        return computerRooms.stream()
                .map(this::convertToOptionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ComputerRoomOptionRspVO> getComputerRoomOptionsByCity(String city) {
        log.info("根据城市查询机房选项，城市: {}", city);

        List<ComputerRoom> computerRooms = list(new LambdaQueryWrapper<ComputerRoom>()
                .eq(ComputerRoom::getCity, city)
                .orderByAsc(ComputerRoom::getName));

        return computerRooms.stream()
                .map(this::convertToOptionVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<ComputerRoomOptionRspVO> getComputerRoomOptionsByOperator(String operator) {
        log.info("根据运营商查询机房选项，运营商: {}", operator);

        List<ComputerRoom> computerRooms = list(new LambdaQueryWrapper<ComputerRoom>()
                .eq(ComputerRoom::getOperator, operator)
                .orderByAsc(ComputerRoom::getName));

        return computerRooms.stream()
                .map(this::convertToOptionVO)
                .collect(Collectors.toList());
    }

    @Override
    public ComputerRoomStatisticsRspVO getComputerRoomStatistics() {
        log.info("获取机房统计信息");

        // 机房总数
        long totalCount = count();

        // 城市数量
        List<String> cities = getAllCities();
        long cityCount = cities.size();

        // 运营商数量
        List<String> operators = getAllOperators();
        long operatorCount = operators.size();

        // 本月新增机房数量
        YearMonth currentMonth = YearMonth.now();
        LocalDateTime monthStart = currentMonth.atDay(1).atStartOfDay();
        LocalDateTime monthEnd = currentMonth.atEndOfMonth().atTime(23, 59, 59);

        long monthlyAddedCount = count(new LambdaQueryWrapper<ComputerRoom>()
                .between(ComputerRoom::getCreateTime, monthStart, monthEnd));

        return ComputerRoomStatisticsRspVO.builder()
                .totalCount(totalCount)
                .cityCount(cityCount)
                .operatorCount(operatorCount)
                .monthlyAddedCount(monthlyAddedCount)
                .build();
    }

    @Override
    public Boolean checkComputerRoomNameExists(String name, Long excludeId) {
        LambdaQueryWrapper<ComputerRoom> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ComputerRoom::getName, name);

        if (Objects.nonNull(excludeId)) {
            queryWrapper.ne(ComputerRoom::getId, excludeId);
        }

        return count(queryWrapper) > 0;
    }

    @Override
    public List<ComputerRoomRspVO> searchComputerRoomByName(String name) {
        log.info("根据名称模糊查询机房，关键字: {}", name);

        List<ComputerRoom> computerRooms = list(new LambdaQueryWrapper<ComputerRoom>()
                .like(StringUtils.hasText(name), ComputerRoom::getName, name)
                .orderByAsc(ComputerRoom::getName));

        return computerRooms.stream()
                .map(computerRoom -> {
                    ComputerRoomRspVO rspVO = new ComputerRoomRspVO();
                    BeanUtils.copyProperties(computerRoom, rspVO);
                    return rspVO;
                })
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getAllCities() {
        log.info("获取所有城市列表");

        return baseMapper.selectList(new LambdaQueryWrapper<ComputerRoom>()
                        .select(ComputerRoom::getCity)
                        .groupBy(ComputerRoom::getCity)
                        .orderByAsc(ComputerRoom::getCity))
                .stream()
                .map(ComputerRoom::getCity)
                .collect(Collectors.toList());
    }

    @Override
    public List<String> getAllOperators() {
        log.info("获取所有运营商列表");

        return baseMapper.selectList(new LambdaQueryWrapper<ComputerRoom>()
                        .select(ComputerRoom::getOperator)
                        .groupBy(ComputerRoom::getOperator)
                        .orderByAsc(ComputerRoom::getOperator))
                .stream()
                .map(ComputerRoom::getOperator)
                .collect(Collectors.toList());
    }

    /**
     * 转换为选项VO
     *
     * @param computerRoom 机房实体
     * @return 选项VO
     */
    private ComputerRoomOptionRspVO convertToOptionVO(ComputerRoom computerRoom) {
        return ComputerRoomOptionRspVO.builder()
                .id(computerRoom.getId())
                .name(computerRoom.getName())
                .city(computerRoom.getCity())
                .operator(computerRoom.getOperator())
                .build();
    }
}




